<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <script src="https://unpkg.com/three@0.130.1/build/three.js"></script>
    <script src="https://unpkg.com/cannon@0.6.2/build/cannon.js"></script>
    <script src="https://unpkg.com/camera-controls@1.30.0/dist/camera-controls.js"></script>
    <script>
      CameraControls.install({ THREE: THREE })

      const clock = new THREE.Clock()
      const scene = new THREE.Scene()
      const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000)
      camera.up.set(0, 0, 1)
      // camera.position.set(0, 2, 5)
      camera.position.set(560.9963573929965, 70.84660458139314, 57.6087987372104)
      camera.lookAt(0, 0, 0)
      const renderer = new THREE.WebGLRenderer()
      renderer.setSize(window.innerWidth, window.innerHeight)
      document.body.appendChild(renderer.domElement)
      const cameraControls = new CameraControls(camera, renderer.domElement)

      const axesHelper = new THREE.AxesHelper(500)
      scene.add(axesHelper)

      const size = 1000
      const divisions = 10
      const gridHelper = new THREE.GridHelper(size, divisions)
      gridHelper.rotation.x = (90 * Math.PI) / 180

      scene.add(gridHelper)

      const world = new CANNON.World()
      world.gravity.set(0, 0, -9.8 * 50)
      world.broadphase = new CANNON.NaiveBroadphase()
      world.solver.iterations = 5

      // Create a plane
      const groundShape = new CANNON.Plane()
      const groundBody = new CANNON.Body({
        mass: 0,
        shape: groundShape,
      })

      groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), -Math.PI / 2)

      world.addBody(groundBody)

      createBox()
      function createBox() {
        var halfExtents = new CANNON.Vec3(15, 15, 15)
        var boxShape = new CANNON.Box(halfExtents)

        var boxBody = new CANNON.Body({
          mass: 1,
          linearDamping: 0.2,
          angularDamping: 0.4,
          material: new CANNON.Material({ friction: 0.5, restitution: 5 }),
        })
        boxBody.addShape(boxShape)

        boxBody.angularVelocity.set(50 * Math.random() * randPM(), 50 * Math.random() * randPM(), 50 * Math.random() * randPM())

        world.addBody(boxBody)

        var boxGeometry = new THREE.BoxGeometry(halfExtents.x * 2, halfExtents.y * 2, halfExtents.z * 2)
        const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })

        var boxMesh = new THREE.Mesh(boxGeometry, material)
        boxMesh.userData = boxBody

        scene.add(boxMesh)
        world.addBody(boxBody)
        boxBody.position.z = 300
        boxMesh.position.z = 300
      }

      const animate = function () {
        requestAnimationFrame(animate)

        updatePhysics()
        const delta = clock.getDelta()
        const isUpdate = cameraControls.update(delta)
        if (isUpdate) {
          const c = camera
          console.log(`${c.position.x},${c.position.y},${c.position.z}`)
        }

        renderer.render(scene, camera)
      }

      animate()

      function updatePhysics() {
        // world.step
        world.step(1 / 60) //第一个参数是以固定步长更新物理世界参数（详情请看api）
        scene.children.forEach(d => {
          //遍历场景中的子对象，如果对象的isMesh属性为true，我们就将更新改对象的position和quaternion属性（他们对应的刚体数据存在对应的userData中）。
          if (d.isMesh == true) {
            d.position.copy(d.userData.position)
            d.quaternion.copy(d.userData.quaternion)
          }
        })
      }

      // const world = new CANNON.World()
      // world.gravity.set(0, 0, -9.8 * 50)
      // world.broadphase = new CANNON.NaiveBroadphase()
      // world.solver.iterations = 5

      // // Create a plane
      // const groundShape = new CANNON.Plane()
      // const groundBody = new CANNON.Body({
      //   mass: 0,
      //   shape: groundShape,
      // })

      // groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), -Math.PI / 2)

      // world.addBody(groundBody)

      // createBox()
      // function createBox() {
      //   var halfExtents = new CANNON.Vec3(15, 15, 15)
      //   var boxShape = new CANNON.Box(halfExtents)

      //   var boxBody = new CANNON.Body({ mass: 1 })
      //   boxBody.addShape(boxShape)
      //   world.addBody(boxBody)

      //   var boxGeometry = new THREE.BoxGeometry(halfExtents.x * 2, halfExtents.y * 2, halfExtents.z * 2)
      //   const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })

      //   var boxMesh = new THREE.Mesh(boxGeometry, material)
      //   boxMesh.userData = boxBody

      //   scene.add(boxMesh)
      //   world.addBody(boxBody)
      //   scene.add(boxMesh)
      //   boxBody.position.y = 30
      //   boxBody.position.z = 30
      //   boxBody.position.z = 200
      //   boxMesh.position.z = 200
      // }
      function randPM() {
        return Math.random() > 0.5 ? 1 : -1
      }
    </script>
  </body>
</html>
